import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Button, Table, Modal, Switch } from "antd";
import { EditOutlined, DeleteOutlined } from '@ant-design/icons';
import axios from "axios";
import UserForm from "../../../components/UserForm";
import { readToken } from '../../../util';
/** @import {User, Role, Right, ReactState, Region} from '../../../types' */
/** @import {FormInstance} from 'antd' */
/** @import {ColumnType, RecordType} from 'antd/es/table' */


function UserList() {
    /** @type {ReactState<UserRoleDTO[]>} */
    const [users, setUsers] = useState([]);
    /** @type {ReactState<Region[]>} */
    const [regions, setRegions] = useState([]);
    /** @type {ReactState<User>} */
    const [currentEditUser, setCurrentEditUser] = useState(null);
    
    const [addModalOpened, setAddModalOpended] = useState(false);
    const [updateModalOpened, setUpdateModalOpended] = useState(false);
    /** @type {React.MutableRefObject<FormInstance>} */
    const addFormRef = useRef(null);
    /** @type {React.MutableRefObject<FormInstance>} */
    const updateFormRef = useRef(null);

    /** @type {ColumnType<User>} */
    const columns = [
        {
            title: "区域",
            dataIndex: "region",
            render: (region) => <b>{ region === "" ? "全球" : region }</b>,
            filters: [
                ...regions.map(r => ({ text: r.title, value: r.value })),
                { text: "全球", value: "" }
            ],
            onFilter: (value, record) => value === record.region
        },
        {
            title: "角色名称",
            dataIndex: "role",
            /** @type {(role: Role) => string} */
            render: (role) => role.roleName
        },
        {
            title: "用户名",
            dataIndex: "username"
        },
        {
            title: "用户状态",
            /** @type {(u: User)} */
            render: (u) => <Switch checked={u.roleState} onClick={() => handleDisable(u)} />
        },
        {
            title: "操作",
            /** @type {(item: User)} */
            render: (u) => (
                <div>
                    <Button danger shape="circle" icon={<DeleteOutlined />} onClick={() => handleDelete(u)}></Button>
                    <Button type="primary" shape="circle" icon={<EditOutlined />} onClick={() => handleEdit(u)} />
                </div>
            )
        }
    ];
    const loggedInUser = useMemo(readToken, []);
    // 拉取数据
    const fetchData = useCallback(() => {
        axios.get("/users?_embed=role")
            .then((res) => {
                /** @type {UserRoleDTO[]} */
                let users = res.data;
                setUsers(users.filter((user) => {
                    if (loggedInUser.role.roleType === 1)
                        return true;
                    else if (loggedInUser.username === user.username)
                        return true;
                    else
                        return user.role.roleType > loggedInUser.role.roleType &&
                            user.region === loggedInUser.region;
                }));
            });
        axios.get("/regions")
            .then((res) => setRegions(res.data));
    }, [loggedInUser]);
    useEffect(() => { fetchData(); }, [fetchData]);

    /** 删除用户 @type {(user: User) => void} */
    const handleDelete = async (user) => {
        await axios.delete("/users/" + user.id);
        await fetchData();
    };

    /** 禁用/启用用户 @type {(user: User) => void} */
    const handleDisable = async (user) => {
        // TODO Immutable
        user.roleState = !user.roleState;
        setUsers([...users]);
        await axios.patch("/users/" + user.id, {
            roleState: user.roleState
        });
        await fetchData();
    };

    /** 修改用户 @type {(u: User) => void} */
    const handleEdit = (u) => {
        setUpdateModalOpended(true);
        setCurrentEditUser(u);
        // TODO 如何等待状态更新
        updateFormRef.current.setFieldsValue(u);
    };

    const handleAddModalOk = () => {
        addFormRef.current.validateFields()
            .then((data) => {
                axios.post("/users", { ...data, roleState: true, default: false })
                .then((res) => {
                        fetchData();
                        addFormRef.current.resetFields();
                        setAddModalOpended(false);
                        console.log("AddUser", res.data);
                    });
            })
            .catch((error) => {
                console.log(error);
            });
    };
    const handleAddModalCancel = setAddModalOpended.bind(undefined, false);

    const handleUpdateModalOk = () => {
        updateFormRef.current.validateFields()
            .then((data) => {
                let newUser = {...currentEditUser, ...data};
                axios.put("/users/" + newUser.id, newUser)
                .then((res) => {
                        fetchData();
                        updateFormRef.current.resetFields();
                        setUpdateModalOpended(false);
                        console.log("EditUser", res.data);
                    });
            })
            .catch((error) => {
                console.log(error);
            });
    };
    const handleUpdateModalCancel = setUpdateModalOpended.bind(undefined, false);

    return (
        <div>
            <Button type="primary" onClick={setAddModalOpended.bind(undefined, true)}>添加用户</Button>
            <Table dataSource={users} columns={columns} rowKey={(item) => item.id } pagination={{ pageSize: 5 }}/>
            <Modal title="添加用户" open={addModalOpened} onOk={handleAddModalOk} onCancel={handleAddModalCancel}>
                <UserForm ref={addFormRef} type="create" />
            </Modal>
            {/* forceRender 强制渲染，是为了避免 updateFormRef.current == null 的情况 */}
            {/* 因为需要先设置数据，再打开模态框。如果不强制渲染，就没法提前拿到 Form 的 ref */}
            <Modal forceRender title="更新用户" open={updateModalOpened} onOk={handleUpdateModalOk} onCancel={handleUpdateModalCancel}>
                <UserForm ref={updateFormRef} type="update" />
            </Modal>
        </div>
    );
}

export default UserList;